#include <fmt/core.h>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <vector>

#define NUM 5

int cnt = 1000;

pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t gcond = PTHREAD_COND_INITIALIZER;

/**
 * @brief 一个简单的Run类，用于存储和操作两个整数。
 *
 * 该类的主要功能是初始化和存储两个整数值_i和_j。构造函数接受两个整数参数i和j，并将它们初始化为成员变量_i和_j。
 * 构造函数内部会将传入的参数i和j重置为0，但这一行为并不会影响成员变量的值。
 *
 */
class Run
{
public:
    // 构造函数，初始化_i和_j为传入的参数i和j
    Run(int i, int j) : _i(i), _j(j)
    {
        // 将传入的参数i和j赋值为0
        i = 0;
        j = 0;
    }
    ~Run() {}

private:
    int _i;
    int _j;
};

// 定义一个线程运行函数
void *threadrun(void *args)
{
    // 将传入的参数转换为字符串
    std::string name = static_cast<const char *>(args);
    // 无限循环
    while (true)
    {
        // 加锁
        pthread_mutex_lock(&glock);
        // 等待条件变量
        pthread_cond_wait(&gcond, &glock);
        // 打印线程名称和计数器值
        fmt::println("{} 计算: {}", name, cnt);
        // 计数器加一
        cnt++;
        // 解锁
        pthread_mutex_unlock(&glock);
    }
}

int main()
{
    // 创建一个线程向量
    std::vector<pthread_t> threads;
    // 循环创建NUM个线程
    for (int i = 0; i < NUM; i++)
    {
        // 创建线程ID
        pthread_t tid;
        // 创建线程名称
        char *name = new char[64];
        // 将线程名称格式化为"thread-数字"的形式
        snprintf(name, 64, "thread-%d", i);
        // 创建线程
        int n = pthread_create(&tid, nullptr, threadrun, name);
        // 等待1秒
        sleep(1);
    }

    // 等待3秒
    sleep(3);

    // 每隔一秒唤醒一个线程
    while (true)
    {
        // 唤醒所有线程
        fmt::println("唤醒所有线程...");
        pthread_cond_broadcast(&gcond);

        // 唤醒一个线程
        fmt::println("唤醒一个线程...");
        pthread_cond_signal(&gcond);
        // 等待1秒
        sleep(1);
    }

    // 等待所有线程结束
    for (auto &id : threads)
    {
        // 等待线程结束
        int m = pthread_join(id, nullptr);
        (void)m;
    }

    // 返回0
    return 0;
}